package br.unirio.webdisco.dao.impl;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import br.unirio.webdisco.dao.conn.BasePostgresDAO;
import br.unirio.webdisco.entity.DNA;
import br.unirio.webdisco.entity.Doenca;
import br.unirio.webdisco.entity.Pesquisa;

public class PesquisaPostgresDAO extends BasePostgresDAO<Pesquisa> {

	@Override
	public void incluir(Pesquisa pesquisa) throws Exception {
		Connection connection = criaConexao(false);
		String sql = "INSERT INTO Pesquisa (IdPesquisa, IdUsuario, Padrao, Probabilidade, IdDoenca) ";
			   sql += "VALUES (nextval('SEQ_IdPesquisa'),?,?,?,?);";
			   
			   
		PreparedStatement stmt = null;

		try {
			stmt = connection.prepareStatement(sql);
			stmt.setInt(1, pesquisa.getIdUsuario());
			stmt.setString(2, pesquisa.getPadrao());
			stmt.setFloat(3, pesquisa.getProbabilidade());
			stmt.setInt(4, pesquisa.getIdDoenca());
			
			int retorno = stmt.executeUpdate();
			if (retorno == 0) {
				connection.rollback();
				throw new SQLException(
						"Ocorreu um erro inesperado no momento de inserir dados de local no banco!");
			}
			connection.commit();

		} catch (SQLException e) {
			connection.rollback();
			throw e;
		} finally {
			try {
				stmt.close();
				this.fechaConexao();
			} catch (SQLException e) {
				throw e;
			}

		}	
		
	}

	@Override
	public void alterar(Pesquisa pesquisa) throws Exception {
		Connection connection = criaConexao(false);
		String sql =  "UPDATE pesquisa SET IdUsuario = ?, Padrao = ?, Probabilidade = ?, idDoenca = ? ";
			   sql += "WHERE idPesquisa = ?";
			   
		PreparedStatement stmt = null;
		try {
			stmt = connection.prepareStatement(sql);
			stmt.setInt(1, pesquisa.getIdUsuario());
			stmt.setString(2, pesquisa.getPadrao());
			stmt.setFloat(3, pesquisa.getProbabilidade());
			stmt.setInt(4, pesquisa.getIdDoenca());
			stmt.setInt(5, pesquisa.getIdPesquisa());
			
			int retorno = stmt.executeUpdate();
			if (retorno == 0) {
				connection.rollback();
				throw new SQLException(
						"Ocorreu um erro inesperado no momento de alterar dados de local no banco!");
			}
			connection.commit();

		} catch (SQLException e) {
			connection.rollback();
			throw e;
		} finally {
			try {
				stmt.close();
				this.fechaConexao();
			} catch (SQLException e) {
				throw e;
			}

		}		
	}

	@Override
	public void excluir(Pesquisa pesquisa) throws Exception {
		Connection connection = criaConexao(false);
		String sql = "DELETE FROM pesquisa WHERE IdPesquisa = ?";
		PreparedStatement stmt = null;
		try {
			stmt = connection.prepareStatement(sql);
			stmt.setInt(1, pesquisa.getIdPesquisa());
			
			int retorno = stmt.executeUpdate();
			if (retorno == 0) {
				connection.rollback();
				throw new SQLException(
						"Ocorreu um erro inesperado no momento de remover dados de local no banco!");
			}
			connection.commit();

		} catch (SQLException e) {
			connection.rollback();
			throw e;
		} finally {
			try {
				stmt.close();
				this.fechaConexao();
			} catch (SQLException e) {
				throw e;
			}

		}
	}

	@Override
	public Integer count() throws Exception {
		Connection connection = criaConexao(false);
		String sql = "SELECT COUNT(*) AS Count FROM Pesquisa ";
		
		
		PreparedStatement stmt = null;
		ResultSet rs = null;
		Integer countPesquisa = null;
		
		try {
			stmt = connection.prepareStatement(sql);
			rs = stmt.executeQuery();
			while (rs.next()) 	
				countPesquisa = rs.getInt("Count");
				
			
		} catch (SQLException e) {
			throw e;
		} finally {
			try {
				stmt.close();
				rs.close();
				this.fechaConexao();
			} catch (SQLException e) {
				throw e;
			}

		}
		return countPesquisa;
	}
	
	@Override
	public List<Pesquisa> listar(Integer paginaTamanho, Integer paginaAtual) throws Exception {
		Connection connection = criaConexao(false);
		String sql = "SELECT PES.idpesquisa, PES.idusuario, PES.iddoenca, PES.padrao, PES.probabilidade, DOE.doenca, USU.Nome FROM Pesquisa PES LEFT JOIN Doenca DOE ON PES.IdDoenca = DOE.IdDoenca LEFT JOIN USUARIO USU ON PES.idusuario = USU.idusuario LIMIT ? OFFSET ?*?";
		
		
		PreparedStatement stmt = null;
		ResultSet rs = null;
		Pesquisa pesquisa= null;
		List<Pesquisa> listaPesquisa = new ArrayList<Pesquisa>();
		
		try {
			stmt = connection.prepareStatement(sql);
			stmt.setInt(1, paginaTamanho);
			stmt.setInt(2, paginaAtual);
			stmt.setInt(3, paginaTamanho);
			rs = stmt.executeQuery();
			while (rs.next()) 
			{
				pesquisa = new Pesquisa();
				pesquisa.setIdPesquisa(rs.getInt("IdPesquisa"));
				pesquisa.setNomePesquisador(rs.getString("nome"));
				pesquisa.setIdUsuario(rs.getInt("IdUsuario"));
				pesquisa.setIdDoenca(rs.getInt("IdDoenca"));
				pesquisa.setDoenca(rs.getString("Doenca"));
				pesquisa.setPadrao(rs.getString("Padrao"));
				pesquisa.setProbabilidade(rs.getFloat("Probabilidade"));
				
				listaPesquisa.add(pesquisa);
				
			}
		} catch (SQLException e) {
			throw e;
		} finally {
			try {
				stmt.close();
				rs.close();
				this.fechaConexao();
			} catch (SQLException e) {
				throw e;
			}

		}
		return listaPesquisa;
	}
	
	
	@Override
	public Pesquisa consultarPorId(Integer id) throws Exception {
		Connection connection = criaConexao(false);
		String sql = "SELECT * FROM Pesquisa WHERE IdPesquisa = ? ";
		PreparedStatement stmt = null;
		ResultSet rs = null;
		Pesquisa pesquisa= null;
		try {
			stmt = connection.prepareStatement(sql);
			stmt.setInt(1, id);
			rs = stmt.executeQuery();
			if (rs.next()) {
				pesquisa = new Pesquisa();
				pesquisa.setIdPesquisa(rs.getInt("IdPesquisa"));
				pesquisa.setIdUsuario(rs.getInt("IdUsuario"));
				pesquisa.setIdDoenca(rs.getInt("IdDoenca"));
				pesquisa.setPadrao(rs.getString("Padrao"));
				pesquisa.setProbabilidade(rs.getFloat("Probabilidade"));
			}
		} catch (SQLException e) {
			throw e;
		} finally {
			try {
			
				if(stmt != null)
					stmt.close();
				
				if(rs != null)
					rs.close();
				
				this.fechaConexao();

			} catch (SQLException e) {
				throw e;
			}

		}
		return pesquisa;
	}

	public boolean verificaPermissao(Integer idUsuarioLogado, Integer idPesquisa) throws Exception {
		Connection connection = criaConexao(false);
		String sql = "SELECT * FROM Pesquisa WHERE IdUsuario = ? AND IdPesquisa = ?";
		PreparedStatement stmt = null;
		ResultSet rs = null;
		try {
			stmt = connection.prepareStatement(sql);
			stmt.setInt(1, idUsuarioLogado);
			stmt.setInt(2, idPesquisa);
			rs = stmt.executeQuery();
			if (rs.next()) {
				return true;
			}
		} catch (SQLException e) {
			throw e;
		} finally {
			try {
			
				if(stmt != null)
					stmt.close();
				
				if(rs != null)
					rs.close();
				
				this.fechaConexao();

			} catch (SQLException e) {
				throw e;
			}

		}
		return false;
	}
	
	@Override
	public List<Pesquisa> consultar(String parametros) throws Exception {
		Connection connection = criaConexao(false);
		String sql = "SELECT * FROM Pesquisa WHERE 1 = 1 ";
		sql += parametros;
		
		PreparedStatement stmt = null;
		ResultSet rs = null;
		Pesquisa pesquisa= null;
		List<Pesquisa> listaPesquisa = new ArrayList<Pesquisa>();
		
		try {
			stmt = connection.prepareStatement(sql);
			rs = stmt.executeQuery();
			while (rs.next()) 
			{
				pesquisa = new Pesquisa();
				pesquisa.setIdPesquisa(rs.getInt("IdPesquisa"));
				pesquisa.setIdUsuario(rs.getInt("IdUsuario"));
				pesquisa.setPadrao(rs.getString("Padrao"));
				pesquisa.setProbabilidade(rs.getFloat("Probabilidade"));
				pesquisa.setIdDoenca(rs.getInt("Doenca"));
				
				listaPesquisa.add(pesquisa);
				
			}
		} catch (SQLException e) {
			throw e;
		} finally {
			try {
				stmt.close();
				rs.close();
				this.fechaConexao();
			} catch (SQLException e) {
				throw e;
			}

		}
		return listaPesquisa;
	}
	
	
	public String retornaDNA(Integer idUsuario)
	{	
	
		String dna = new String();
		try{
			DNAPostgresDAO DNAConsulta = new DNAPostgresDAO();
			DNA arquivo = new DNA();
			arquivo = DNAConsulta.consultarPorUsuario(idUsuario);
			
			FileInputStream fstream = new FileInputStream("C:\\uploads\\" + arquivo.getSequencia());
			
			DataInputStream in = new DataInputStream(fstream);
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			String strLine;
			
			while ((strLine = br.readLine()) != null) 
				dna = strLine;
			
			
			in.close();
			return dna;
		}catch(Exception e)
		{
			return null;
		}
	}
	
	public boolean relatorioDoencas(Integer idUsuario) throws Exception {
		Connection connection = criaConexao(false);
		String sql = "SELECT PES.idpesquisa, PES.idusuario, PES.iddoenca, PES.padrao, PES.probabilidade, DOE.doenca, USU.Nome FROM Pesquisa PES LEFT JOIN Doenca DOE ON PES.IdDoenca = DOE.IdDoenca LEFT JOIN USUARIO USU ON PES.idusuario = USU.idusuario ORDER BY doenca ";
		
		PreparedStatement stmt = null;
		ResultSet rs = null;
		Pesquisa pesquisa= null;
		
		try {
			stmt = connection.prepareStatement(sql);
			rs = stmt.executeQuery();
			
			String dna = retornaDNA(idUsuario);
			if(dna == null) return false;
			
			String doencaAnterior = null;
			float  probabilidadeAnterior = 1;
			boolean primeiraDoenca = true;
			
			FileWriter fstream = new FileWriter("C:\\uploads\\ProprencaoDoencas.txt");
			BufferedWriter out = new BufferedWriter(fstream);
			
			while (rs.next()) 
			{	
				pesquisa = new Pesquisa();
				pesquisa.setIdPesquisa(rs.getInt("IdPesquisa"));
				pesquisa.setNomePesquisador(rs.getString("nome"));
				pesquisa.setIdUsuario(rs.getInt("IdUsuario"));
				pesquisa.setIdDoenca(rs.getInt("IdDoenca"));
				pesquisa.setDoenca(rs.getString("Doenca"));
				pesquisa.setPadrao(rs.getString("Padrao"));
				pesquisa.setProbabilidade(rs.getFloat("Probabilidade"));
				
				for(int i = 10; i <= dna.length(); i++)
				{	
					if(dna.substring(i- pesquisa.getPadrao().length(),i).contentEquals(pesquisa.getPadrao()))
					{
						if(primeiraDoenca)
						{
							doencaAnterior = pesquisa.getDoenca();
							primeiraDoenca = false;
						}
						if(doencaAnterior.contentEquals(pesquisa.getDoenca()))
						{
							probabilidadeAnterior *= pesquisa.getProbabilidade();
							if(i == dna.length())
							{
								out.write(doencaAnterior  + " : " + probabilidadeAnterior);
								out.newLine();
							}
						}else
						{
							out.write(doencaAnterior  + " : " + probabilidadeAnterior);
							out.newLine();
							doencaAnterior = pesquisa.getDoenca();
							probabilidadeAnterior = pesquisa.getProbabilidade();
						}
					}
				}
			}
			out.close();
			return true;
		} catch (SQLException e) {
			throw e;
		} finally {
			try {
				stmt.close();
				rs.close();
				this.fechaConexao();
			} catch (SQLException e) {
				throw e;
			}

		}
	}
	
}

